package net.chrone.query.util;


import java.util.HashSet;


import net.chrone.query.util.DingTalkUtil;
import net.chrone.query.util.PropertiesUtil;
import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.exceptions.JedisConnectionException;


public class RedisClient {
	private static Logger logger = Logger.getLogger(RedisClient.class);
//	private static JedisSentinelPool jedisPool;//非切片客户端连接池,用于单机redis
	private static JedisPool jedisPool;//非切片客户端连接池,用于单机redis

	//	private static final String REDIS_IP = SdkUtil.getStringValue("redisIp");
//	private static final Integer REDIS_PORT = SdkUtil.getIntValue("redisPort");
	private static final String REDIS_IP_PORT_1= PropertiesUtil.getProperty("redisIpPort1");
	private static final String REDIS_IP_PORT_2= PropertiesUtil.getProperty("redisIpPort2");
	private static final String REDIS_IP_PORT_3= PropertiesUtil.getProperty("redisIpPort3");
	private static final String REDIS_PASSWORD = PropertiesUtil.getProperty("redisPasswd");



	public static final String CACHE_PREFIX_MCHNT = "redis_prefix_mchnt_";
	//public static final String CACHE_PREFIX_BILL_SET = "redis_prefix_billset_";
	public static final String CACHE_PREFIX_ID = "redis_prefix_id_";
	//public static final String CACHE_PREFIX_MCHNT_STL = "redis_prefix_mchnt_stl_";
	//public static final String CACHE_PREFIX_IP = "redis_prefix_ip_";
	public static final String CACHE_CHANNEL_CONFIG = "redis_channel_config_";//后面拼接通道id 或者 商户id_支付渠道id
	public static final String CACHE_MER_FIXQR_TOKEN = "redis_merchant_fixqr_token_";//商户固定二维码token
	public static final String CACHE_MER_CODE_URL = "redis_merchant_code_url_";//商户扫码动态二维码  保存十五分钟
	public static final String REDIS_JD_H5PAY_URL = "redis_jd_h5pay_url_";//京东h5支付保存拼装的form表单
	/**
	 * 初始化jedis连接池
	 */
	private static void initalPool() {
		JedisPoolConfig config = new JedisPoolConfig();
		//设置最大连接数（100个足够用了，没必要设置太大）
		config.setMaxTotal(100);
		//最大空闲连接数
		config.setMaxIdle(10);
		//获取Jedis连接的最大等待时间（50秒）
		config.setMaxWaitMillis(50 * 1000);
		//在获取Jedis连接时，自动检验连接是否可用
		config.setTestOnBorrow(true);
		//在将连接放回池中前，自动检验连接是否有效
		config.setTestOnReturn(true);
		//自动测试池中的空闲连接是否都是可用连接
		config.setTestWhileIdle(true);


		// 使用HashSet添加多个sentinel
		HashSet<String> sentinels = new HashSet<String>();
		// 添加sentinel主机和端口
		sentinels.add(REDIS_IP_PORT_1);
		sentinels.add(REDIS_IP_PORT_2);
		sentinels.add(REDIS_IP_PORT_3);
//		jedisPool = new JedisSentinelPool(PropertiesUtil.getProperty("mymaster"),sentinels,config,REDIS_PASSWORD);
		jedisPool = new JedisPool("127.0.0.1");
		logger.info("jedis init success!!!");

	}

	/**
	 * 获取Jedis实例
	 */
	private static Jedis getJedis() {
		if (null == jedisPool) {
			initalPool();
		}

		int timeoutCount = 0;
		while (true) {
			try {
				if (null != jedisPool) {
					logger.info("jedisInfo ... NumActive=" + jedisPool.getNumActive()
							+ ", NumIdle=" + jedisPool.getNumIdle()
							+ ", NumWaiters=" + jedisPool.getNumWaiters()
							+ ", isClosed=" + jedisPool.isClosed());
					return jedisPool.getResource();
				}



			} catch (Exception e) {
				if (e instanceof JedisConnectionException) {
					timeoutCount++;
					logger.warn("getJedis timeoutCount=[" + timeoutCount + "]");
					if (timeoutCount > 10) {
						break;
					}
				} else {
					break;
				}
				logger.error("GetJedis error,", e);
				DingTalkUtil.sendDingMsg("GetJedis error,连续获取10次，未获取到连接");

			}
		}
		return null;
	}

	/**
	 * 释放Jedis资源
	 *
	 * @param jedis
	 */
	public static void returnResource(Jedis jedis) {
		if (null != jedis) {
			jedis.close();
		}
	}

	/**
	 * 安全取得redis连接
	 * @param key redis key
	 * @return
	 */
	public synchronized static String getByKey(String key){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		String value = "";
		while(i<2){
			Jedis jedis=null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return "";
				}
				value = jedis.get(key);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("getByKey异常，key="+key,e);
				DingTalkUtil.sendDingMsg("Redis,getByKey异常，key="+key);
			}finally {
				returnResource(jedis);
			}

		}
		return value;
	}
	/**
	 *
	 * @param key   redis key
	 * @param value redis value
	 * @return
	 */
	public synchronized static String set(String key,String value){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		String result = "";
		while(i<2){
			Jedis jedis=null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return "";
				}
				logger.info("插入新的缓存数据key："+key);

				result = jedis.set(key, value);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.set异常，key="+key+",value="+value,e);
				DingTalkUtil.sendDingMsg("RedisClient.set异常，key="+key+",value="+value);
			}finally {
				returnResource(jedis);
			}

		}
		return result;
	}

	/**
	 * 安全验证redis key
	 * @param key
	 * @return
	 */
	public synchronized static Boolean exisit(String key){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		boolean result = false;
		while(i<2){
			Jedis jedis=null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return false;
				}
				result = jedis.exists(key);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.exisit异常，key="+key,e);
				DingTalkUtil.sendDingMsg("RedisClient.exisit异常，key="+key);
			}finally {
				returnResource(jedis);
			}

		}
		return result;
	}

	public synchronized static Long inc(String key){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long result = 0L;
		while(i<2){
			Jedis jedis=null;
			try{
				jedis= getJedis();
				if (null == jedis) {
					return 0L;
				}
				result=jedis.incr(key);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.inc异常，key="+key,e);
				DingTalkUtil.sendDingMsg("RedisClient.inc异常，key="+key);
			}finally {
				returnResource(jedis);
			}

		}
		return result;
	}

	public synchronized static Long incBy(String key,long amount){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long result = 0L;
		while(i<2){
			Jedis jedis=null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return 0L;
				}
				result=jedis.incrBy(key, amount);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.incBy异常，key="+key+",amount="+amount,e);
				DingTalkUtil.sendDingMsg("RedisClient.incBy异常，key="+key+",amount="+amount);
			}finally {
				returnResource(jedis);
			}

		}
		return result;
	}

	//存set
	public synchronized static Long sadd(String key,String value){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long result = 0L;
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return 0L;
				}
				result=jedis.sadd(key, value);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.sadd异常，key="+key+",value="+value,e);
				DingTalkUtil.sendDingMsg("RedisClient.sadd异常，key="+key+",value="+value);
			}finally {
				returnResource(jedis);

			}

		}
		return result;
	}




	public static Long decrBy(String key, int amount) {
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long result = 0L;
		while(i<2){
			Jedis jedis=null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return 0L;
				}
				result=jedis.decrBy(key, amount);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.decrBy异常，key="+key+",amount="+amount,e);
				DingTalkUtil.sendDingMsg("RedisClient.incBy异常，key="+key+",amount="+amount);
			}finally {
				returnResource(jedis);
			}

		}
		return result;
	}


	public synchronized static String setex(String key, int seconds,String value){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		String result ="";
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return "";
				}
				result=jedis.setex(key,seconds,value);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.setex异常，key="+key+",value="+value+",seconds="+seconds,e);
				DingTalkUtil.sendDingMsg("RedisClient.setex异常，key="+key+",value="+value+",seconds="+seconds);

			}finally {
				returnResource(jedis);
			}
		}
		return result;
	}
	
	public synchronized static Long setex(String key, int seconds){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long result = null;
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return null;
				}
				result=jedis.expire(key, seconds);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.setex异常，key="+key+",seconds="+seconds,e);
				DingTalkUtil.sendDingMsg("RedisClient.setex异常，key="+key+",seconds="+seconds);
				
			}finally {
				returnResource(jedis);
			}
		}
		return result;
	}
	
	public synchronized static Long lpush(String key, String value){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long length = null;
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					logger.error("获取redis实例失败");
					return null;
				}
				length=jedis.lpush(key, value);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.lpush异常，key="+key+",value="+value,e);
				DingTalkUtil.sendDingMsg("RedisClient.lpush异常，key="+key+",value="+value);
				
			}finally {
				returnResource(jedis);
			}
		}
		return length;
	}
	
	public synchronized static String ltrim(String key, Long start, Long end){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		String result ="";
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return "";
				}
				result=jedis.ltrim(key, start, end);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.ltrim异常，key="+key+",start="+start+",end="+end,e);
				DingTalkUtil.sendDingMsg("RedisClient.ltrim异常，key="+key+",start="+start+",end="+end);

			}finally {
				returnResource(jedis);
			}
		}
		return result;
	}
	
	public synchronized static Long llen(String key){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long length = null;
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					logger.error("获取redis实例失败");
					return null;
				}
				length=jedis.llen(key);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.setex异常，key="+key,e);
				DingTalkUtil.sendDingMsg("RedisClient.setex异常，key="+key);
				
			}finally {
				returnResource(jedis);
			}
		}
		return length;
	}

	public synchronized static String lindex(String key, Long index){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		String result ="";
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return "";
				}
				result=jedis.lindex(key, index);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.lindex异常，key="+key+",index="+index, e);
				DingTalkUtil.sendDingMsg("RedisClient.lindex异常，key="+key+",index="+index);
			}finally {
				returnResource(jedis);
			}
		}
		return result;
	}
	
	public synchronized static Long ttl(String key){
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long result = null;
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return null;
				}
				result=jedis.ttl(key);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.lindex异常，key="+key, e);
				DingTalkUtil.sendDingMsg("RedisClient.lindex异常，key="+key);
				
			}finally {
				returnResource(jedis);
			}
		}
		return result;
	}

	public static void main(String[] args) throws InterruptedException {
		long currentTime = System.currentTimeMillis() ;
		long currentTime1 =currentTime+(long)10*60*1000;//10分钟
		int i=0;
		String ss="";
		while(System.currentTimeMillis()<currentTime1){
			RedisClient.set("a",Integer.toString(i));
			ss=RedisClient.getByKey("a");
			System.out.println("ssssssssssssss="+ss);
			i++;
		}
		long endTime=System.currentTimeMillis();
		logger.info("FileUtil.decompressZip()耗费时间： "+(endTime-currentTime)+" ms");
	}


    public static long delByKey(String key) {
		//如果是sentinel监测到master挂掉，正在切换到salve时异常，则重新获取一次redis
		int i=0;
		Long result = 0L;
		while(i<2){
			Jedis jedis =null;
			try{
				jedis = getJedis();
				if (null == jedis) {
					return 0L;
				}
				result=jedis.del(key);
				i=10;
			}catch(Exception e){
				i++;
				logger.error("RedisClient.delByKey异常，key="+key,e);
				DingTalkUtil.sendDingMsg("RedisClient.sadd异常，key="+key);
			}finally {
				returnResource(jedis);
			}

		}
		return result;
    }
}
